﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StockFinder.DataAccess;
using StockFinder.Model;
using StockFinder.Services.Extractors;
using StockFinder.Services.Extractors.Yahoo;
using StockFinder.Model.Enumerations;
using log4net;

namespace StockFinder.Services.Engines.Yahoo
{
    public class YahooHistoricPriceLoadRunEngine
    {
        private static readonly ILog _Log = LogManager.GetLogger(typeof(YahooHistoricPriceLoadRunEngine));

        private SymbolDataAccess _SymbolsDataAccess;
        private PriceLoadRunDataAccess _PriceLoadRunDataAccess;
        private DailyPriceDataAccess _DailyPricesDataAccess;
        private readonly IHistoricPricesExtractor _HistoricPriceExtractor;

        public YahooHistoricPriceLoadRunEngine()
        {
            _SymbolsDataAccess = new SymbolDataAccess();
            _PriceLoadRunDataAccess = new PriceLoadRunDataAccess();
            _DailyPricesDataAccess = new DailyPriceDataAccess();
            _HistoricPriceExtractor = new YahooHistoricPriceExtractor();
        }

        public void Run(DateTime dateFrom, DateTime dateTo)
        {
            /* create new load run entry */

            _Log.InfoFormat("*** NEW PRICE LOAD RUN ***");

            PriceLoadRun job = new PriceLoadRun();
            job.DateFrom = dateFrom;
            job.DateTo = dateTo;
            job.RunDate = DateTime.Now;

            /* insert job */

            _PriceLoadRunDataAccess.InsertPriceLoadRun(job);

            _Log.InfoFormat("PriceLoadJob: {0}, DateFrom: {1}, DateTo: {2}, RunDate: {3}",
                job.PriceLoadRunId, dateFrom, dateTo, job.RunDate);

            /* grab symbols */

            _Log.InfoFormat("Getting Symbols");

            List<Symbol> symbols = SymbolDataAccess.GetAllSymbols();

            /* loop symbols */

            _Log.InfoFormat("Beginning symbols loop");

            foreach (Symbol symbol in symbols)
            {
                /* create result container */

                _Log.InfoFormat("SymbolId: {0}, Symbol: {1}", symbol.SymbolId, symbol.Name);

                PriceLoadRunResult priceLoadRunResult = new PriceLoadRunResult();
                priceLoadRunResult.PriceLoadRun = job;
                priceLoadRunResult.Symbol = symbol;

                /* get prices */

                try
                {
                    _Log.DebugFormat("Extracting prices...");

                    HistoricPricesExtract extractResult = _HistoricPriceExtractor.ExtractHistoricPrices(
                        dateFrom,
                        dateTo,
                        symbol.Name);

                    //save the result
                    priceLoadRunResult.Result = extractResult.HistoricPricesExtractResult.ToString();

                    _Log.InfoFormat("Result: {0}", priceLoadRunResult.Result);

                    //go ok?
                    if (extractResult.HistoricPricesExtractResult == HistoricPricesExtractResult.SUCCESS)
                    {
                        _Log.InfoFormat("Looping prices...");

                        //loop the prices
                        foreach (DailyPrice dailyPrice in extractResult.DailyPrices)
                        {
                            //does it exist?
                            if (!_DailyPricesDataAccess.DoesDailyPriceExistByDateAndSymbol(dailyPrice))
                            {
                                _Log.DebugFormat("{0} price inserted", dailyPrice.PriceDate);

                                //no so insert
                                _DailyPricesDataAccess.InsertDailyPrice(dailyPrice);
                            }
                            else
                            {
                                _Log.DebugFormat("{0} price already exists", dailyPrice.PriceDate);
                            }
                        }
                    }
                    else
                    {
                        //something happened so couldnt down load prices - will be logged further down
                    }
                }
                catch (Exception exception)
                {
                    _Log.ErrorFormat("Error occurred: {0}", exception.ToString());

                    //something unexpected happened
                    priceLoadRunResult.Result = "Error occurred: " + exception.ToString();
                }

                /* insert result */

                _PriceLoadRunDataAccess.InsertPriceLoadRunResult(priceLoadRunResult);

                _Log.InfoFormat("Inserted price load run result");
            }
        }
    }
}

